home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / utilities / text / less-278.lha / less-278 / src.lha / source / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-01  |  6.8 KB  |  329 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Entry point, initialization, miscellaneous routines.
  30.  */
  31.  
  32. #include "less.h"
  33. #include "position.h"
  34.  
  35. public char *    every_first_cmd = NULL;
  36. public int    new_file;
  37. public int    is_tty;
  38. public IFILE    curr_ifile = NULL_IFILE;
  39. public IFILE    old_ifile = NULL_IFILE;
  40. public struct scrpos initial_scrpos;
  41. public int    any_display = FALSE;
  42. public int    wscroll;
  43. public char *    progname;
  44. public int    quitting;
  45.  
  46. extern int    quit_at_eof;
  47. extern int    cbufs;
  48. extern int    errmsgs;
  49. extern int    screen_trashed;
  50. extern int    force_open;
  51.  
  52. #if LOGFILE
  53. public int    logfile = -1;
  54. public int    force_logfile = FALSE;
  55. public char *    namelogfile = NULL;
  56. #endif
  57.  
  58. #if EDITOR
  59. public char *    editor;
  60. public char *    editproto;
  61. #endif
  62.  
  63. #if TAGS
  64. extern char *    tagfile;
  65. extern char *    tagoption;
  66. extern int    jump_sline;
  67. #endif
  68.  
  69.  
  70.  
  71. /*
  72.  * Entry point.
  73.  */
  74. int
  75. main(argc, argv)
  76.     int argc;
  77.     char *argv[];
  78. {
  79.     IFILE ifile;
  80.  
  81. #ifdef __EMX__
  82.     _response(&argc, &argv);
  83.     _wildcard(&argc, &argv);
  84. #endif
  85.  
  86.     progname = *argv++;
  87.  
  88.     /*
  89.      * Process command line arguments and LESS environment arguments.
  90.      * Command line arguments override environment arguments.
  91.      */
  92.     init_cmds();
  93.     init_prompt();
  94.     init_charset();
  95.     init_option();
  96.     scan_option(getenv("LESS"));
  97.  
  98. #define    isoptstring(s)    (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
  99.     while (--argc > 0 && (isoptstring(argv[0]) || isoptpending()))
  100.         scan_option(*argv++);
  101. #undef isoptstring
  102.  
  103.     if (isoptpending())
  104.     {
  105.         /*
  106.          * Last command line option was a flag requiring a
  107.          * following string, but there was no following string.
  108.          */
  109.         nopendopt();
  110.         quit(QUIT_OK);
  111.     }
  112.  
  113. #if EDITOR
  114.     editor = getenv("VISUAL");
  115.     if (editor == NULL || *editor == '\0')
  116.     {
  117.         editor = getenv("EDITOR");
  118.         if (editor == NULL || *editor == '\0')
  119.             editor = EDIT_PGM;
  120.     }
  121.     editproto = getenv("LESSEDIT");
  122.     if (editproto == NULL || *editproto == '\0')
  123.         editproto = "%E ?lm+%lm. %f";
  124. #endif
  125.  
  126.     /*
  127.      * Call get_ifile with all the command line filenames
  128.      * to "register" them with the ifile system.
  129.      */
  130.     ifile = NULL_IFILE;
  131.     while (--argc >= 0)
  132.     {
  133. #if MSOFTC || OS2
  134.         /*
  135.          * Because the "shell" doesn't expand filename patterns,
  136.          * treat each argument as a filename pattern rather than
  137.          * a single filename.  
  138.          * Expand the pattern and iterate over the expanded list.
  139.          */
  140.         struct textlist tlist;
  141.         char *gfilename;
  142.         char *filename;
  143.         
  144.         gfilename = glob(*argv++);
  145.         if (gfilename == NULL)
  146.             continue;
  147.         init_textlist(&tlist, gfilename);
  148.         filename = NULL;
  149.         while ((filename = forw_textlist(&tlist, filename)) != NULL)
  150.             ifile = get_ifile(filename, ifile);
  151.         free(gfilename);
  152. #else
  153.         ifile = get_ifile(*argv++, ifile);
  154. #endif
  155.     }
  156.     /*
  157.      * Set up terminal, etc.
  158.      */
  159.     is_tty = isatty(1);
  160.     if (!is_tty)
  161.     {
  162.         /*
  163.          * Output is not a tty.
  164.          * Just copy the input file(s) to output.
  165.          */
  166.         if (nifile() == 0)
  167.         {
  168.             if (edit_stdin() == 0)
  169.                 cat_file();
  170.         } else if (edit_first() == 0)
  171.         {
  172.             do {
  173.                 cat_file();
  174.             } while (edit_next(1) == 0);
  175.         }
  176.         quit(QUIT_OK);
  177.     }
  178.  
  179.     init_mark();
  180.     raw_mode(1);
  181.     get_term();
  182.     get_editkeys();
  183.     open_getchr();
  184.     init_signals(1);
  185.  
  186.     /*
  187.      * Select the first file to examine.
  188.      */
  189. #if TAGS
  190.     if (tagoption != NULL)
  191.     {
  192.         /*
  193.          * A -t option was given.
  194.          * Verify that no filenames were also given.
  195.          * Edit the file selected by the "tags" search,
  196.          * and search for the proper line in the file.
  197.          */
  198.         if (nifile() > 0)
  199.         {
  200.             error("No filenames allowed with -t option", NULL_PARG);
  201.             quit(QUIT_ERROR);
  202.         }
  203.         findtag(tagoption);
  204.         if (tagfile == NULL)
  205.             quit(QUIT_ERROR);
  206.         if (edit(tagfile))  /* Edit file which contains the tag */
  207.             quit(QUIT_ERROR);
  208.         /*
  209.          * Search for the line which contains the tag.
  210.          * Set up initial_scrpos so we display that line.
  211.          */
  212.         initial_scrpos.pos = tagsearch();
  213.         if (initial_scrpos.pos == NULL_POSITION)
  214.             quit(QUIT_ERROR);
  215.         initial_scrpos.ln = jump_sline;
  216.     } else
  217. #endif
  218.     if (nifile() == 0)
  219.     {
  220.         if (edit_stdin())  /* Edit standard input */
  221.             quit(QUIT_ERROR);
  222.     } else 
  223.     {
  224.         if (edit_first())  /* Edit first valid file in cmd line */
  225.             quit(QUIT_ERROR);
  226.     }
  227.  
  228.     init();
  229.     commands();
  230.     quit(QUIT_OK);
  231.     /*NOTREACHED*/
  232. }
  233.  
  234. /*
  235.  * Copy a string, truncating to the specified length if necessary.
  236.  * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
  237.  */
  238.     public void
  239. strtcpy(to, from, len)
  240.     char *to;
  241.     char *from;
  242.     unsigned int len;
  243. {
  244.     strncpy(to, from, len);
  245.     to[len-1] = '\0';
  246. }
  247.  
  248. /*
  249.  * Copy a string to a "safe" place
  250.  * (that is, to a buffer allocated by calloc).
  251.  */
  252.     public char *
  253. save(s)
  254.     char *s;
  255. {
  256.     register char *p;
  257.  
  258.     p = (char *) ecalloc(strlen(s)+1, sizeof(char));
  259.     strcpy(p, s);
  260.     return (p);
  261. }
  262.  
  263. /*
  264.  * Allocate memory.
  265.  * Like calloc(), but never returns an error (NULL).
  266.  */
  267.     public VOID_POINTER
  268. ecalloc(count, size)
  269.     int count;
  270.     unsigned int size;
  271. {
  272.     register VOID_POINTER p;
  273.  
  274.     p = (VOID_POINTER) calloc(count, size);
  275.     if (p != NULL)
  276.         return (p);
  277.     error("Cannot allocate memory", NULL_PARG);
  278.     quit(QUIT_ERROR);
  279.     /*NOTREACHED*/
  280. }
  281.  
  282. /*
  283.  * Skip leading spaces in a string.
  284.  */
  285.     public char *
  286. skipsp(s)
  287.     register char *s;
  288. {
  289.     while (*s == ' ' || *s == '\t')    
  290.         s++;
  291.     return (s);
  292. }
  293.  
  294. /*
  295.  * Exit the program.
  296.  */
  297.     public void
  298. quit(status)
  299.     int status;
  300. {
  301.     static int save_status;
  302.  
  303.     /*
  304.      * Put cursor at bottom left corner, clear the line,
  305.      * reset the terminal modes, and exit.
  306.      */
  307.     if (status < 0)
  308.         status = save_status;
  309.     else
  310.         save_status = status;
  311.     quitting = 1;
  312.     edit((char*)NULL);
  313.     if (any_display)
  314.         clear_bot();
  315.     deinit();
  316.     flush();
  317.     raw_mode(0);
  318. #if MSOFTC
  319.     /* 
  320.      * If we don't close 2, we get some garbage from
  321.      * 2's buffer when it flushes automatically.
  322.      * I cannot track this one down  RB
  323.      * The same bug shows up if we use ^C^C to abort.
  324.      */
  325.     close(2);
  326. #endif
  327.     exit(status);
  328. }
  329.